package com.xuecheng.media.service.jobhandler;

import com.xuecheng.base.utils.Mp4VideoUtil;
import com.xuecheng.media.model.po.MediaProcess;
import com.xuecheng.media.service.MediaFileProcessService;
import com.xuecheng.media.service.MediaFileService;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;

import java.util.List;
import java.util.concurrent.*;

/**
 * 视频任务处理
 */
@Slf4j
@Component
public class VideoTask {
    @Autowired
    private MediaFileProcessService mediaFileProcessService;
    @Autowired
    private MediaFileService mediaFileService;
    @Value("${videoprocess.ffmpegpath}")
    String ffmpegpath;


    /**
     * 2、分片广播任务
     */
    @XxlJob("videoJobHandler")
    public void shardingJobHandler() throws Exception {

        // 分片参数
        int shardIndex = XxlJobHelper.getShardIndex();
        int shardTotal = XxlJobHelper.getShardTotal();
        //cpu最大核心数
        int processors = Runtime.getRuntime().availableProcessors();
        //待处理的任务
        List<MediaProcess> mediaProcessList = mediaFileProcessService.getMediaProcessList(shardTotal, shardIndex, processors);
        //任务数量
        int size=mediaProcessList.size();
        if(size<=0){
            return;
        }
        //创建一个线程池
        ExecutorService executorService = Executors.newFixedThreadPool(size);
        //使用的计数器
        CountDownLatch countDownLatch = new CountDownLatch(size);
        mediaProcessList.forEach(mediaProcess -> {
            //将任务加入线程池
            executorService.execute(()->{
                try {
                    //开启任务
                    Long taskId = mediaProcess.getId();
                    boolean b = mediaFileProcessService.startTask(taskId);
                    if(!b){
                        log.debug("任务抢占失败,任务id:{}",taskId);
                        return;
                    }
                    String bucket = mediaProcess.getBucket();
                    String objectName = mediaProcess.getFilePath();

                    //文件Id就是md5值
                    String fileId = mediaProcess.getFileId();

                    //下载minio视频到本地
                    File file = mediaFileService.downloadFileFromMinIO(bucket, objectName);
                    if(file==null){
                        log.debug("视频下载出错,任务id:{},bucket:{},object:{}",taskId,bucket,objectName);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"视频下载到本地出错");
                        return;
                    }
                    //处理结束的视频文件
                    String video_path = file.getAbsolutePath();
                    //转换后mp4的文件名称
                    String mp4_name=fileId+".mp4";
                    File mp4File=null;
                    try {
                         mp4File = File.createTempFile("minio", ".mp4");
                    } catch (IOException e) {
                        log.debug("创建临时文件异常，{}",e.getMessage());
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"创建临时文件异常");
                        return;
                    }
                    String mp4_path = mp4File.getAbsolutePath();
                    //创建工具类对象
                    Mp4VideoUtil videoUtil = new Mp4VideoUtil(ffmpegpath,video_path,mp4_name,mp4_path);
                    //开始视频转码，成功将返回success
                    String result = videoUtil.generateMp4();
                    if(!result.equals("success")){
                        log.debug("视频转码失败，原因：{},bucket:{},objectName:{}",result,bucket,objectName);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"视频转码失败");
                        return;
                    }
                    //上传到minio
                    boolean b1 = mediaFileService.addMediaFilesToMinIO(mp4File.getAbsolutePath(), "video/mp4", bucket, objectName);
                    if(!b1){
                        log.debug("上传mp4到minio失败，任务id",taskId);
                        mediaFileProcessService.saveProcessFinishStatus(taskId,"3",fileId,null,"上传mp4到minio失败");
                        return;
                    }
                    //mp4的url
                    String url = getFilePath(fileId, ".mp4");
                    //任务成功
                    mediaFileProcessService.saveProcessFinishStatus(taskId,"1",fileId,url,"");
                }finally {
                    //计数器减一
                    countDownLatch.countDown();
                }

            });
       });
        //阻塞
        countDownLatch.await(30,TimeUnit.MINUTES);
    }
    private String getFilePath(String fileMd5,String fileExt){
        return   fileMd5.substring(0,1) + "/" + fileMd5.substring(1,2) + "/" + fileMd5 + "/" +fileMd5 +fileExt;
    }
}
